#include "LoginMgr.h"
#include "LoginService.h"
#include "Common/Utility/ServerTime.h"
#include "base/core/com_define.h"
#include "Common/Utility/AccountUtility.h"

LoginMgr::LoginMgr()
{
	m_bAllZoneOpen = false;
}

LoginMgr::~LoginMgr()
{

}

bool LoginMgr::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetLoginService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
		return false;

	pMessageDispatch->registerServerHandler(EMODULE_ID_SERV_SYS, this);
	pMessageDispatch->registerDBProxyHandler(EMODULE_ID_LOGIN, this);

	return true;
}

bool LoginMgr::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetLoginService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
		return false;

	pMessageDispatch->unregisterServerHandler(EMODULE_ID_SERV_SYS);
	pMessageDispatch->unregisterDBProxyHandler(EMODULE_ID_LOGIN);

	return true;
}

LoginCBInfo* LoginMgr::GetLoginCBInfoBySessionId(uint32_t Id)
{
	LOGINCBMAP::iterator iter = m_loginCBInfos.find(Id);
	if (iter == m_loginCBInfos.end())
		return nullptr;

	return &iter->second;
}

bool LoginMgr::onClientMessage(uint32_t actionId, RECV_PACKAGE &package)
{
    bool result = false;
    bool retCode = false;

	switch (actionId)
	{
	case CLIENT_TO_LOGIN_PING:
	{
		PingRsp rsp;
		rsp.set_currentmstime(ServerTime::Tick());
		g_GetLoginService()->SendDataToClient(package.session, LOGIN_TO_CLIENT_PING, &rsp);
		LogDebugFmtPrint("Client Ping To LoginServer, pakageLen:%d", package.sizeAfterHead);
	}
		break;
	case CLIENT_TO_LOGIN_ACCOUNT_LOGIN:
		retCode = LoginReq(package);
		MMOLOG_PROCESS_ERROR(retCode);
		break;
	case CLIENT_TO_LOGIN_SELECT_ZONE:
		retCode = ClientSelectZoneReq(package);
		MMOLOG_PROCESS_ERROR(retCode);
		break;
	default:
		LogErrFmtPrint("login recv msg cannt find handle func, cmd:%d, clientId:%d", actionId, package.session->GetUserData().v32);
		MMOLOG_PROCESS_ERROR(false);
		break;
	}
    result = true;
Exit0:
	return result;
}

void LoginMgr::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	if (actionId == MASTER_SERVER_PROTOCOL_PING)
		return;

	LogDebugFmtPrint("Login Mgr Recv Srv message cmd:%d", package.cmd);
	switch (actionId)
	{
	case MASTER_REGISTE_LOGIN_RSP:
		RegisterRsp(package);
		break;
	case MASTER_NOTIFY_LOGIN_NEW_ZONE:
		NotifyNewZone(package);
		break;
	case MASTER_TO_LOGIN_OPEN_STATE:
		NotifyZoneOpenState(package);
		break;
	case MASTER_TO_LOGIN_ALL_ZONE_OPEN_STATE:
		NotifyAllZoneOpenState(package);
		break;
	case MASTER_TO_LOGIN_WHITE_LST:
		NotifyWhiteLst(package);
		break;
	case LOGIN_WEBSDK_RSP:
		LoginWebRspFromWeb(package);
		break;
	default:
		break;
	}
}

void LoginMgr::onDBProxyMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case DBPROXY_PROTOCOL_UID_RSP:
		GameUidRsp(package);
		break;
	default:
		break;
	}
}

void* LoginMgr::AddClient(uint32_t clientId, ISession* pSession)
{
	LoginCBInfo  cb;
	cb.state = LOGIN_STATE::LOGIN_STATE_CONNECT;
	cb.clientId = clientId;
	cb.connectTimeSec = ServerTime::UnixSec();
	cb.pSession = pSession;

	pair<LOGINCBMAP::iterator, bool> pret;
	pret = m_loginCBInfos.insert(make_pair(cb.clientId, cb));
	if (!pret.second)
		return nullptr;

	return (void*)&pret.first->second;
}

void LoginMgr::DisconnectClient(uint32_t clientId)
{
	m_loginCBInfos.erase(clientId);
}

bool LoginMgr::RegisterReq()
{
	LogDebugFmtPrint("login server send register request info  master");
	LoginRegisterReq registe;
	registe.set_id(g_GetLoginService()->GetID());
	return g_GetLoginService()->SendDataToMaster(LOGIN_REGISTE_MASTER_REQ, &registe);
}

bool LoginMgr::RegisterRsp(RECV_PACKAGE & package)
{
	LoginRegisterRsp registeRsp;
	if (!registeRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("RegisterReq parse error, loginId:%d", g_GetLoginService()->GetID());
		return false;
	}
	MMOLOG_ASSERT(registeRsp.retcode() == RET_SUCCESS);

	LoginZone loginZone;
	ZoneInfo zone;
	char buf[16];
	int length = 0;

	m_channelZones.clear();
	LogDebugFmtPrint("loginserver recv register info from master, size:%d, allZoneOpen:%d", package.sizeAfterHead, m_bAllZoneOpen);
	for (int i = 0; i < registeRsp.zones_size(); i++)
	{
		string channbuf;
		zone = registeRsp.zones(i);
		loginZone.whiteLst = zone.whitelst();
		loginZone.cZone.set_ip(zone.ip());
		loginZone.cZone.set_port(zone.port());
		loginZone.cZone.set_zid(zone.zid());
		loginZone.cZone.set_name(zone.name());
		loginZone.cZone.set_zstate(zone.zstate());

		for (int j = 0; j < zone.channelid_size(); j++)
		{
			m_channelZones[zone.channelid(j)][zone.zid()] = loginZone;

			length = snprintf(buf, 16, "%d,", zone.channelid(j));
			if (length > 15)
				continue;
			buf[length + 1] = '\0';
			channbuf += buf;
		}

		LogInfoFmtPrint("register from master:%d, name:%s, whitelist:%d, zoneState:%d, ip:%s, port:%d, channs:%s", 
			zone.zid(), zone.name().c_str(), zone.whitelst(), zone.zstate(), zone.ip().c_str(), zone.port(), channbuf.c_str());
	}


	m_bAllZoneOpen = registeRsp.allzoneopen();
	m_whiteLst.clear();
	m_recommendZoneIds.clear();
	m_unOpenZones.clear();

	for (int j = 0; j < registeRsp.whitelst_size(); j++)
		m_whiteLst.insert(registeRsp.whitelst(j));

	for (int d = 0; d < registeRsp.recommendzoneids_size(); d++)
		m_recommendZoneIds.push_back(registeRsp.recommendzoneids(d));

	UnOpenZoneInfo uoZone;
	ClientLoginRsp::ChannelZone czone;
	for (int j = 0; j < registeRsp.unopenzones_size(); j++)
	{
		string channbuf;
		uoZone = registeRsp.unopenzones(j);
		czone.set_zid(uoZone.zid());
		czone.set_name(uoZone.name());
		czone.set_zonelstid(uoZone.zonelstid());
		if (uoZone.opentime() > 0)
			czone.set_opentime(uoZone.opentime());

		for (int a = 0; a < uoZone.channelid_size(); a++)
		{
			m_unOpenZones[uoZone.channelid(a)][uoZone.zid()] = czone;

			length = snprintf(buf, 16, "%d,", uoZone.channelid(a));
			if (length > 15)
				continue;
			buf[length + 1] = '\0';
			channbuf += buf;
		}

		LogInfoFmtPrint("register from master unopen zones zid:%d, name:%s, channs:%s, openTime:%lu", czone.zid(), czone.name().c_str(), channbuf.c_str(), uoZone.opentime());
	}
	
	return true;
}

bool LoginMgr::NotifyNewZone(RECV_PACKAGE & package)
{
	NofityNewZoneToLogin  notifyZone;
	if (!notifyZone.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("NotifyNewZone parase error, loginSrvId:%d", g_GetLoginService()->GetID());
		return false;
	}
	m_channelZones.clear();

	LoginZone loginZone;
	ZoneInfo zone;
	int length = 0;
	char buf[16];

	for (int i = 0; i < notifyZone.zones_size(); i++)
	{
		string channbuf;
		zone = notifyZone.zones(i);
		loginZone.whiteLst = zone.whitelst();
		loginZone.cZone.set_zid(zone.zid());
		loginZone.cZone.set_name(zone.name());
		loginZone.cZone.set_zstate(zone.zstate());
		loginZone.cZone.set_ip(zone.ip());
		loginZone.cZone.set_port(zone.port());
		for (int j = 0; j < zone.channelid_size(); j++)
		{
			m_channelZones[zone.channelid(j)][zone.zid()] = loginZone;

			length = snprintf(buf, 16, "%d,", zone.channelid(j));
			if (length > 15)
				continue;
			buf[length + 1] = '\0';
			channbuf += buf;
		}

		LogInfoFmtPrint("master notify login zid:%d, name:%s, whitelist:%d, zoneState:%d, ip:%s, port:%d, channs:%s" 
			, zone.zid(), zone.name().c_str(), loginZone.whiteLst, zone.zstate(), loginZone.cZone.ip().c_str(), loginZone.cZone.port(), channbuf.c_str());
	}
	return true;
}

bool LoginMgr::LoginReq(RECV_PACKAGE& package)
{
    bool result = false;
    bool retCode = false;
	ClientLoginReq login;
	set<string>::iterator iter;
	set<string>::iterator iterEnd;
	uint32_t	 clientId = package.session->GetUserData().v32;
	LoginCBInfo  *pcbInfo = (LoginCBInfo *)package.session->GetUserData().ptr;

	retCode = login.ParseFromArray(package.dataAfterHead, package.sizeAfterHead);
	MMOLOG_PROCESS_ERROR(retCode);

	//只允许玩家请求一次，在服务器作后续操作的时候，过来的消息，都丢弃   add by wangxx
	if (!pcbInfo || pcbInfo->state != LOGIN_STATE_CONNECT)
	{
		LogErrFmtPrint("LoginReq, pcbInfo == null or state !=  LOGIN_STATE_CONNECT client:%d, channelId:%d, pcbInfo:%d, state:%d", clientId, login.channelid());
		MMOLOG_PROCESS_ERROR(false);
	}

	if (!m_bAllZoneOpen)
	{
		//全服不开放
		ClientLoginRsp loginRsp;
		loginRsp.set_err(RET_LOGIN_ACCOUNT_SYSTEM_MAINTENANCE);
		loginRsp.set_uid(0);
		g_GetLoginService()->SendDataToClient(package.session, LOGIN_TO_CLIENT_ACCOUNT_LOGIN, &loginRsp);
		goto Exit0;
	}

	pcbInfo->channelId = login.channelid();
	pcbInfo->clientId = clientId;

	if (pcbInfo->channelId == Chann_Dev)
	{
		std::vector<std::string> elems;
		uint32_t uid = 0;
		MMOLOG_PROCESS_ERROR(login.sdkstring().size()>0);

		std::string lowerAccount = g_TransToLower(login.sdkstring());
		if (StringSplit2Uid(lowerAccount, uid))
		{
			pcbInfo->state = LOGIN_STATE_REQ_UID_FINISH;
			retCode = LoginRsp(uid, clientId, "");
			MMOLOG_PROCESS_ERROR(retCode);
		}
		else
		{
			retCode = GameUidReq(clientId, pcbInfo->channelId, lowerAccount);
			MMOLOG_PROCESS_ERROR(retCode);
		}
	}
	else
	{
		//发送给web服务器去判定
		retCode = LoginWebReqToWeb(login.sdkstring(),pcbInfo);
		MMOLOG_PROCESS_ERROR(retCode);
	}

	//登陆成功，修改clientsesion时间 10分钟 防止频繁断开
	retCode = g_GetLoginService()->ResetSessionTimeOut(pcbInfo->pSession, MAX_CONNECT_TIME_MSEC);
	MMOLOG_PROCESS_ERROR(retCode);

    result = true;
Exit0:
	return result;
}

bool LoginMgr::LoginRsp(uint32_t uid, uint32_t clientId, std::string suid)
{
	LoginCBInfo  *pcbInfo = GetLoginCBInfoBySessionId(clientId);
	if (NULL == pcbInfo)
	{
		LogErrFmtPrint("login Req From Client msg repeated, now client:%d, suid:%s, uid:%d", clientId, suid.c_str(), uid);
		return false;
	}
	pcbInfo->state = LOGIN_STATE_SELECT_ZONE;

	uint64_t now = Time::Now().UnixMSec();
	ClientLoginRsp lrsp;
	lrsp.set_err(RET_SUCCESS);
	lrsp.set_uid(uid);
	AC_CHARACTERS *pcharacters = lrsp.mutable_characters();
	pcharacters->CopyFrom(pcbInfo->characters);
	lrsp.set_logintimestamp(now);
	lrsp.set_zonetime(Time::zoneTime_);
	lrsp.set_sdkrspstring(pcbInfo->sdkRspString);
	uint64_t tokenTime = 0;
	if (g_GetLoginService()->TokenTimeCheck())
		tokenTime = now;
	lrsp.set_token(g_MakeConnectZoneMd5(uid, tokenTime));
	lrsp.set_tokentime(tokenTime);

	bool bwhitelst = CheckWhiteLst(uid);
	ClientLoginRsp::ChannelZone* pZone = nullptr;
	auto iter = m_channelZones.find(pcbInfo->channelId);
	auto iterEnd = m_channelZones.end();
	if (iter != iterEnd)
	{
		auto zIter = iter->second.begin();
		auto zIterEnd = iter->second.end();

		for (; zIter != zIterEnd; zIter++)
		{
			if (zIter->second.whiteLst && !bwhitelst)
			{
				continue;
			}
			pZone = lrsp.add_zones();
			pZone->CopyFrom(zIter->second.cZone);
		}
	}
	else
	{
		LogErrFmtPrint("loginRsp, cannt find channel zones  this channel may not have zones, clientId:%d, uid:%d, channelId:%d", clientId, uid, pcbInfo->channelId);
	}

	for (size_t i = 0; i < m_recommendZoneIds.size(); i++)
		lrsp.add_recommendzoneids(m_recommendZoneIds[i]);

	auto iterUnOpen = m_unOpenZones.find(pcbInfo->channelId);
	if (iterUnOpen != m_unOpenZones.end())
	{
		auto uiter = iterUnOpen->second.begin();
		auto uiterEnd = iterUnOpen->second.end();
		for (; uiter != uiterEnd; uiter++)
		{
			pZone = lrsp.add_unopenzones();
			pZone->CopyFrom(uiter->second);
		}
	}

	LogInfoFmtPrint("LoginRsp ok, uid:%d, channelId:%d, clientId:%d  suid:%s, state:%d, loginstring:%s", uid, pcbInfo->channelId, clientId, suid.c_str(), pcbInfo->state, pcbInfo->sdkRspString.c_str());
	return g_GetLoginService()->SendDataToClient(pcbInfo->pSession, LOGIN_TO_CLIENT_ACCOUNT_LOGIN, &lrsp);
}

bool LoginMgr::GameUidReq(uint32_t clientId, uint32_t channelId, string platformUid)
{
	LoginUidReq uidReq;
	string sUid = g_MakeAccount(platformUid, channelId);
	uidReq.set_channeluid(sUid);
	uidReq.set_clientid(clientId);
	uidReq.set_loginid(g_GetLoginService()->GetID());

	LoginCBInfo  *pcbInfo = GetLoginCBInfoBySessionId(clientId);
	if (!pcbInfo)
	{
		LogErrFmtPrint("GameUidReq  cannt find cb info client:%d, channelId:%d, platformUid:%s", clientId, channelId, platformUid.c_str());
		return false;
	}
	pcbInfo->state = LOGIN_STATE_REQ_UID;
	LogInfoFmtPrint("GameUidReq ok, client:%d, channelId:%d, platformUid:%s, state:%d", clientId, channelId, platformUid.c_str(), pcbInfo->state);

	//向accountDB发送请求uid
	return g_GetLoginService()->SendDataToAccountDB(EMODULE_ID_LOGIN, DBPROXY_PROTOCOL_UID_REQ, &uidReq);
}

bool LoginMgr::GameUidRsp(RECV_PACKAGE &package)
{
	LoginUidRsp uidRsp;
	if (!uidRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("GameUidRsp, size:%d, cmd:%d", package.sizeAfterHead, package.cmd);
		return false;
	}
	uint32_t clientId = uidRsp.clientid();

	LoginCBInfo  *pcbInfo = GetLoginCBInfoBySessionId(clientId);
	if (!pcbInfo)
	{
		LogErrFmtPrint("GameUidRsp, disconnect client:%d, channelId:%s", uidRsp.clientid(),uidRsp.channeluid().c_str());
		return false;
	}

	pcbInfo->state = LOGIN_STATE_REQ_UID_FINISH;
	pcbInfo->uid = uidRsp.uid();

	LoginRsp(pcbInfo->uid, clientId, uidRsp.channeluid());

	LogInfoFmtPrint("GameUidRsp ok, plamltUid:%s, sessionId:%d, uid:%d, state:%d", uidRsp.channeluid().c_str(), uidRsp.clientid(), uidRsp.uid(), pcbInfo->state);
	return true;
}

bool LoginMgr::ClientSelectZoneReq(RECV_PACKAGE &package)
{
	SelectZoneReq selectReq;
	if (!selectReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("ClientSelectZoneReq, ParseFromArray error ");
		return false;
	}

	uint32_t Id = package.session->GetUserData().v32;
	uint32_t zid = selectReq.zid();
	uint32_t uid = selectReq.uid();
	uint32_t channelId = selectReq.channelid();

	LoginCBInfo  *pcbInfo = (LoginCBInfo*)package.session->GetUserData().ptr;
	if (!pcbInfo || pcbInfo->state != LOGIN_STATE_REQ_UID_FINISH)
	{
		LogErrFmtPrint("ClientSelectZoneReq, pcbInfo == null or state != LOGIN_STATE_REQ_UID_FINISH client:%d, uid:%d, zid:%d, channelId:%d, pcbinfo:%d, state:%d", Id, uid, zid,channelId, pcbInfo, pcbInfo->state);
		return false;
	}
	pcbInfo->state = LOGIN_STATE_SELECT_ZONE;

	LoginZone* pZone = GetZoneInfo(channelId, zid);
	if (pZone == nullptr)
	{
		LogErrFmtPrint("there is no zone, channelId:%d, zid:%d, uid:%d", channelId, zid, uid);
		return false;
	}
	if (pZone->cZone.zstate() == ZS_fix && !CheckWhiteLst(uid))
	{
		LogErrFmtPrint("fix zone state cannt player for normal user, channelId:%d, zid:%d, uid:%d", channelId, zid, uid);
		return false;
	}

	uint64_t tokenTime = 0;
	if (g_GetLoginService()->TokenTimeCheck())
		tokenTime = Time::Now().UnixSec();

	SelectZoneRsp zoneRsp;
	zoneRsp.set_ip(pZone->cZone.ip());
	zoneRsp.set_port(pZone->cZone.port());
	zoneRsp.set_token(g_MakeConnectZoneMd5(uid, tokenTime));
	zoneRsp.set_logintimestamp(tokenTime);
	zoneRsp.set_srvsdkstring(pcbInfo->sdkRspString);

	bool ret = g_GetLoginService()->SendDataToClient(pcbInfo->pSession, LOGIN_TO_CLIENT_SELECT_ZONE, &zoneRsp);
	if (!ret)
	{
		LogErrFmtPrint("ClientSelectZoneRsp, send client fail,  client:%d, uid:%d, zid:%d, ip:%s, port:%d", Id, uid, pZone->cZone.zid(), pZone->cZone.ip().c_str(), pZone->cZone.port());
		return false;
	}
	else
		LogInfoFmtPrint("ClientSelectZoneRsp ok,  client:%d, uid:%d, zid:%d, ip:%s, port:%d, state:%d", Id, uid, pZone->cZone.zid(), pZone->cZone.ip().c_str(), pZone->cZone.port(), pcbInfo->state);

	return true;
}

LoginZone*  LoginMgr::GetZoneInfo(uint32_t channelId, uint32_t zid)
{
	auto iter = m_channelZones.find(channelId);
	auto iterEnd = m_channelZones.end();

	if (iter == iterEnd)
		return nullptr;

	auto iterZ = iter->second.find(zid);
	auto iterZEnd = iter->second.end();

	if (iterZ == iterZEnd)
		return nullptr;

	return &iterZ->second;
}

bool LoginMgr::NotifyAllZoneOpenState(RECV_PACKAGE &package)
{
    bool result = false;
    bool retCode = false;
	NofityLoginAllZoneOpenState allzone;
	retCode = allzone.ParseFromArray(package.dataAfterHead, package.sizeAfterHead);
	MMOLOG_PROCESS_ERROR(retCode);
	LogInfoFmtPrint("LoginMgr::NotifyAllZoneOpenState, old:%d, new:%d", m_bAllZoneOpen, allzone.allzoneopen());
	m_bAllZoneOpen = allzone.allzoneopen();
    result = true;
Exit0:
	return result;
}

bool LoginMgr::NotifyZoneOpenState(RECV_PACKAGE &package)
{
    bool result = false;
    bool retCode = false;
	NotifyLoginOpenState  openReq;
	LoginZone *pzone = nullptr;
	uint32_t zid = 0;
	uint32_t channelId = 0;

	retCode = openReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead);
	MMOLOG_PROCESS_ERROR(retCode);
	zid = openReq.zid();

	for (int i = 0; i < openReq.channels_size(); i++)
	{
		channelId = openReq.channels(i);
		pzone = GetZoneInfo(channelId, zid);
		if (pzone == nullptr)
		{
			LogErrFmtPrint("LoginMgr::NotifyZoneOpenState, cannt find loginzone, channelId:%d, zid:%d", channelId, zid);
			continue;
		}
		LogInfoFmtPrint("LoginMgr::NotifyZoneOpenState, change open state, old:%d, new:%d, zoneLstId:%d", pzone->whiteLst, openReq.whitelst(),openReq.zonelstid());
		pzone->whiteLst = openReq.whitelst();
		pzone->cZone.set_zonelstid(openReq.zonelstid());
	}

    result = true;
Exit0:
	return result;
}

bool LoginMgr::NotifyWhiteLst(RECV_PACKAGE &package)
{
    bool result = false;
    bool retCode = false;

	NofityLoginWhiteLst wReq;
	retCode = wReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead);
	MMOLOG_PROCESS_ERROR(retCode);

	if (wReq.whitelst_size() > 0)
	{
		m_whiteLst.clear();
		for (int i = 0; i < wReq.whitelst_size(); i++)
			m_whiteLst.insert(wReq.whitelst(i));
	}
	if (wReq.recommendzoneids_size() > 0)
	{
		m_recommendZoneIds.clear();
		for (int i = 0; i < wReq.recommendzoneids_size(); i++)
			m_recommendZoneIds.push_back(wReq.recommendzoneids(i));
	}

	if (wReq.unopenzones_size() > 0)
	{
		m_unOpenZones.clear();
		UnOpenZoneInfo uoZone;
		ClientLoginRsp::ChannelZone czone;
		int length = 0;
		char buf[16];
		for (int j = 0; j < wReq.unopenzones_size(); j++)
		{
			string channbuf;
			uoZone = wReq.unopenzones(j);
			czone.set_zid(uoZone.zid());
			czone.set_name(uoZone.name());
			czone.set_zonelstid(uoZone.zonelstid());
			if (uoZone.opentime() > 0)
				czone.set_opentime(uoZone.opentime());

			for (int a = 0; a < uoZone.channelid_size(); a++)
			{
				m_unOpenZones[uoZone.channelid(a)][uoZone.zid()] = czone;

				length = snprintf(buf, 16, "%d,", uoZone.channelid(a));
				if (length > 15)
					continue;
				buf[length + 1] = '\0';
				channbuf += buf;
			}

			LogInfoFmtPrint("notify unopenzones from master unopen zones zid:%d, name:%s, channs:%s, openTime:%lu", czone.zid(), czone.name().c_str(), channbuf.c_str(), czone.opentime());
		}
	}

	LogInfoFmtPrint("LoginMgr::NotifyWhiteLst, count:%d", m_whiteLst.size());

    result = true;
Exit0:
	return result;
}


bool LoginMgr::CheckWhiteLst(uint32_t uid)
{
	unordered_set<uint32_t>::iterator iter = m_whiteLst.find(uid);
	unordered_set<uint32_t>::iterator iterEnd = m_whiteLst.end();
	if (iter != iterEnd)
	{
		return true;
	}
	return false;
}

bool LoginMgr::LoginWebReqToWeb(const string& sdkString, LoginCBInfo* pcbInfo)
{
    bool result = false;
    bool retCode = false;
	LoginWebReq lWebReq;

	pcbInfo->state = LOGIN_STATE_VERIFY;
	lWebReq.set_clientid(pcbInfo->clientId);
	lWebReq.set_sdkstring(sdkString);
	lWebReq.set_channelid(pcbInfo->channelId);

	retCode = g_GetLoginService()->SendDataToLoginWeb(LOGIN_WEBSDK_REQ, &lWebReq);
	MMOLOG_PROCESS_ERROR(retCode);

	LogInfoFmtPrint("send login req to web server clientId:%d, channelId:%d,  sdk:%s", pcbInfo->clientId,pcbInfo->channelId, sdkString.c_str());

    result = true;
Exit0:
	return result;
}

bool LoginMgr::LoginWebRspFromWeb(RECV_PACKAGE &package)
{
    bool result = false;
    bool retCode = false;
	LoginWebRsp lwebRsp;
	LoginCBInfo *pcb;
	uint32_t clientId = 0;

	retCode = lwebRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead);
	MMOLOG_PROCESS_ERROR(retCode);
	clientId = lwebRsp.clientid();

	pcb = GetLoginCBInfoBySessionId(clientId);
	if (pcb == nullptr)
	{
		LogErrFmtPrint("LoginWebRspFromWeb, cannt find cbinfo clientId:%d", clientId);
		MMOLOG_PROCESS_ERROR(false);
	}
	pcb->sdkRspString = lwebRsp.sdkrspstring();

	//临时代码
	if (lwebRsp.channelid() == Chann_Dev && lwebRsp.has_openaccount() && lwebRsp.openaccount() == false)
	{
		//全服不开放
		ClientLoginRsp loginRsp;
		loginRsp.set_err(RET_LOGIN_CHARACTER_NOT_ACCOUNT);
		loginRsp.set_uid(0);
		g_GetLoginService()->SendDataToClient(pcb->pSession, LOGIN_TO_CLIENT_ACCOUNT_LOGIN, &loginRsp);
		goto Exit0;
	}

	if (!lwebRsp.success())
	{
		ClientLoginRsp loginRsp;
		loginRsp.set_err(RET_LOGIN_CHANNEL_FAIL);
		loginRsp.set_uid(0);
		g_GetLoginService()->SendDataToClient(pcb->pSession, LOGIN_TO_CLIENT_ACCOUNT_LOGIN, &loginRsp);
		LogErrFmtPrint("LoginWebRspFromWeb, channelId:%d, fail:%s", lwebRsp.channelid(), lwebRsp.failreason().c_str());
		goto Exit0;
	}

	retCode = GameUidReq(clientId, lwebRsp.channelid(), lwebRsp.platuid());
	MMOLOG_PROCESS_ERROR(retCode);

	pcb->characters.CopyFrom(lwebRsp.characters());
    result = true;
Exit0:
	return result;
}